Geomorph has several built-in functions to read landmark data files.
Additionally, one can use standard IO functions in R to read in a text
file. Geomorph also has the ability to digitize 2D or 3D data. For 3D,
one can read in a 3D image in the form of a PLY file.
Data files created using StereoMorph can be read into geomorph using
the readShapes function in StereoMorph
combined with the readland.shapes function in
geomorph. The result is an geomorphShapes object which may
be used in downstream GM analyses.
readland.shapes() (Expand for more details)
This function allows you to extract landmark coordinates from a “shapes,” file in your working environment. The possible arguments, or input values specified by the user, are below:
library(StereoMorph)
myShapes <- readShapes("../Tutorials/Data-figures/Shapes")
mydata <- readland.shapes(myShapes)
#plot lmks
mydata$landmarks$Fish1
## [,1] [,2]
## LM1 11.97986 -14.31232
## LM2 20.74027 -10.27158
## LM3 28.46039 -11.77180
## LM4 29.15027 -14.77224
## LM5 19.69997 -17.07185
Specimens with missing data can still be read using the procedure
above. In these cases, the landmark values will be replaced with
NA, and can be estimated in subsequent data-processing
steps using estimate.missing.
TPS files have an inherent structure similar to the 3d-array data structure used
in geomorph; whereas nts files correspond to a structure similar to
two.d.arrays in geomorph. In both cases, data are read-in
as a 3d-array. You can open tps files in a text editor to get familiar
with their structure. To read a .tps file into geomorph,
use the corresponding function: readland.tps
readland.tps()
tpsdata <- readland.tps("../Tutorials/Data-figures/salamanders.tps")
str(tpsdata)
dim(tpsdata)
tpsdata[,,1]
tpsdata <- readland.tps("../Tutorials/Data-figures/salamanders.tps", specID="imageID") # Specify specimen labels
str(tpsdata)
tpsdata[,,1:2]
With .tps files, missing data may be coded by using negative numbers
for the landmarks. In these cases, readland.tps will prompt
the user to determine whether the negative values are actual landmark
coordinates, or whether they represent missing data. In the latter case,
the landmark values will be replaced with NA, and can be
estimated in subsequent data-processing steps using estimate.missing.
ntsdata <- readland.nts("../Tutorials/Data-figures/RATS.nts")
str(ntsdata)
## num [1:8, 1:2, 1:164] -0.45 -0.59 -0.515 -0.33 0 0.145 -0.045 -0.26 -0.475 -0.28 ...
ntsdata[,,1]
## [,1] [,2]
## [1,] -0.450 -0.475
## [2,] -0.590 -0.280
## [3,] -0.515 -0.120
## [4,] -0.330 0.000
## [5,] 0.000 0.000
## [6,] 0.145 -0.395
## [7,] -0.045 -0.420
## [8,] -0.260 -0.465
In some cases, landmark data for your specimens may be contained in
separate tps or nts files that you want to read simultaneously. The
functions readmulti.tps and readmulti.nts will
allow you to do this:
mtpsdata <- readmulti.tps(c("../Tutorials/Data-figures/test1.tps", "../Tutorials/Data-figures/test2.tps"))
##
## No specID provided; specimens will be numbered 1, 2, 3 ...
##
## No curves detected; all points appear to be fixed landmarks.
##
## No specID provided; specimens will be numbered 1, 2, 3 ...
##
## No curves detected; all points appear to be fixed landmarks.
str(mtpsdata)
## num [1:2, 1:2, 1:10] 119 316 136 151 126 ...
## - attr(*, "dimnames")=List of 3
## ..$ : NULL
## ..$ : NULL
## ..$ : chr [1:10] "1" "2" "3" "4" ...
mtpsdata[,,1]
## [,1] [,2]
## [1,] 119.1888 136.3207
## [2,] 315.6288 150.9804
Note that the list of file paths must be in vector format, that is, in the format of “c(”file1”, “file2”, etc)”
The same can be done with nts files as well:
mtpsdata <- readmulti.nts(c("../Tutorials/Data-figures/Pleth1.nts",
"../Tutorials/Data-figures/Pleth2.nts",
"../Tutorials/Data-figures/Pleth3.nts"))
str(mtpsdata)
## num [1:12, 1:2, 1:3] 8.89 9.27 5.56 1.87 1.28 ...
## - attr(*, "dimnames")=List of 3
## ..$ : NULL
## ..$ : NULL
## ..$ : chr [1:3] "../Tutorials/Data-figures/Pleth1.nts_1" "../Tutorials/Data-figures/Pleth2.nts_1" "../Tutorials/Data-figures/Pleth3.nts_1"
mtpsdata[,,1]
## [,1] [,2]
## [1,] 8.89372 53.77644
## [2,] 9.26840 52.77072
## [3,] 5.56104 54.21028
## [4,] 1.87340 52.75100
## [5,] 1.28180 53.18484
## [6,] 1.24236 53.32288
## [7,] 0.84796 54.70328
## [8,] 3.35240 55.76816
## [9,] 6.29068 55.70900
## [10,] 8.87400 55.25544
## [11,] 10.74740 55.43292
## [12,] 14.39560 52.75100
Another file type that is sometimes encountered is a Morphologika
file; developed for the Morphologika package. One can read these files
using geomorph also, using the function
read.morphologika:
morphdata <- read.morphologika("../Tutorials/Data-figures/mophologikaexample.txt")
str(morphdata)
## List of 4
## $ coords : num [1:31, 1:3, 1:15] 16 15 15 16.3 15.9 ...
## ..- attr(*, "dimnames")=List of 3
## .. ..$ : NULL
## .. ..$ : NULL
## .. ..$ : chr [1:15] "Specimen 1" "Specimen 2" "Specimen 3" "Specimen 4" ...
## $ labels : chr [1:15, 1] "Female" "Female" "Female" "Female" ...
## ..- attr(*, "dimnames")=List of 2
## .. ..$ : chr [1:15] "Specimen 1" "Specimen 2" "Specimen 3" "Specimen 4" ...
## .. ..$ : chr "Sex"
## $ wireframe: num [1:40, 1:2] 1 22 6 24 15 15 17 15 5 23 ...
## $ polygon : num [1:37, 1:3] 7 8 9 9 6 11 10 11 13 12 ...
dim(morphdata$coords)
## [1] 31 3 15
morphdata$coords[,,1]
## [,1] [,2] [,3]
## [1,] 16.01 24.17 11.18
## [2,] 15.00 24.86 11.16
## [3,] 14.96 25.54 11.52
## [4,] 16.26 24.36 11.48
## [5,] 15.89 26.61 11.83
## [6,] 17.16 25.33 12.35
## [7,] 18.22 23.65 11.12
## [8,] 18.77 23.75 11.21
## [9,] 18.72 24.24 11.62
## [10,] 19.26 25.71 10.33
## [11,] 18.21 25.39 12.05
## [12,] 19.32 25.91 14.39
## [13,] 17.45 26.36 13.70
## [14,] 14.51 26.93 11.50
## [15,] 15.93 26.94 12.36
## [16,] 17.11 26.94 13.63
## [17,] 18.69 26.98 14.67
## [18,] 19.50 27.03 15.03
## [19,] 15.75 29.67 10.89
## [20,] 14.96 29.08 11.07
## [21,] 14.92 28.36 11.48
## [22,] 15.85 29.43 11.37
## [23,] 15.93 27.16 12.02
## [24,] 17.07 28.57 12.32
## [25,] 17.90 30.15 11.26
## [26,] 18.62 30.00 11.18
## [27,] 18.69 29.71 11.45
## [28,] 19.14 28.53 10.28
## [29,] 18.17 28.51 12.08
## [30,] 19.25 28.15 14.23
## [31,] 17.48 27.52 13.71
Sometimes, we may wish to digitize directly from 3D images. These
come in the form of ply files, and geomorph has the ability
to read, and then digitize such images.
mandible <- read.ply("../data/Mandible.ply", ShowSpecimen = TRUE)
rgl.bg(color = c("#ceecf0"))
rglwidget()
One may have additional data, covariates, or other specimen
information that one wishes to read into R for downstream analyses. As
we are working in the R environment, one is free to do so using a
variety of read functions. Below we provide an example for
a data matrix, and a phylogeny:
Salamanders <- read.csv("../data/salamanders.csv", header=FALSE)
library(ape)
tree <- read.tree("../data/plethtree.tre")
plot(tree)
Most analytical functions in geomorph require one’s data
be in 3D array (nxpxk) format. The functions discussed above return data
in array format automatically as part of the read-in process. However,
if your raw data are not in tps, nts, or morphologika format, the
arrayspecs function can be used to convert them into a 3D
array:
mydata <- arrayspecs(as.matrix(Salamanders), 12, 2)
str(mydata)
## int [1:12, 1:2, 1:287] 448 472 266 110 97 92 56 158 306 453 ...
Make certain that the number of landmarks (the p argument) is correct! If the incorrect value is input, but that value is still divisible by the number of dimensions (k), the function will still run. This will result in an array with the incorrect number of specimens, each with the incorrect number of landmarks.